import axios from 'axios'
import router from '@/router'
import { useUserStore } from '@/stores'
import { ElLoadingService } from 'element-plus'
import { isBlob } from '@/utils'

const Code = {
  /** 请求成功 */
  SUCCESS: 200,
  /** 认证失败 */
  AUTH_FAILD: 401,
  /** 无访问权限 */
  NOACCESS: 403,
  /** 未找到资源 */
  NOTFOUND: 404,
  /** 请求方法错误 */
  METHOD_ERROR: 405,
  /** 服务器错误 */
  SERVER_ERROR: 500
}

let isShow = true,
  loadingInstance = null,
  /** 请求次数 */
  reqCounter = 0

function closeLoading() {
  reqCounter--
  if (reqCounter <= 0) {
    loadingInstance?.close()
  }
}

axios.defaults.baseURL = import.meta.env.VITE_API_PATH

// 数据类型
axios.defaults.headers.post['Content-Type'] = 'application/json'

// 请求超时时间（ms）
axios.defaults.timeout = 1000 * 60
if (!axios.isInterceptorAdded) {
  // 请求拦截器
  axios.interceptors.request.use(
    config => {
      // loadingInstance = ElLoadingService({
      //   background: 'transparent'
      // })
      reqCounter++
      if (config.headers) {
        config.headers.Authorization = useUserStore().token
      }
      return config
    },
    error => {
      closeLoading()
      console.dir('request error: ', error)

      return Promise.reject(error)
    }
  )

  // 响应拦截器
  axios.interceptors.response.use(
    response => {
      // 2xx 范围内的状态码都会触发该函数。
      closeLoading()

      const { data } = response

      switch (data.code) {
        case Code.SUCCESS:
          return data
        case Code.AUTH_FAILD:
          unauthorized()
          return Promise.reject(response)
        default:
          console.log('response default : ', response)
          if (isBlob(data)) {
            return response
          }

          ElMessage({
            message: data.msg ?? '系统异常',
            type: 'error',
            duration: 3000
          })
          return Promise.reject(response)
      }
    },
    error => {
      // 超出 2xx 范围的状态码都会触发该函数。
      closeLoading()
      if (!error) {
        ElMessage({
          message: '请求异常',
          type: 'error',
          duration: 5000
        })
        return Promise.reject()
      }
      console.log('response error: ', error.toJSON())

      const { response } = error

      if (!response) {
        ElMessage({
          message: '请求未响应',
          type: 'error',
          duration: 5000
        })
        return Promise.reject()
      }

      switch (response.status) {
        case Code.AUTH_FAILD:
          unauthorized()
          break
        case Code.NOACCESS:
          ElMessage.error(response.data.msg + ' 没有访问权限')
          break
        case Code.NOTFOUND: //=>找不到页面
          ElMessage.error(response.config.url + ' 方法不存在')
          break
        case Code.METHOD_ERROR:
          ElMessage.error('请求方法错误 ' + response.statusText)
          break
        case Code.SERVER_ERROR: //=>找不到页面
          ElMessage({
            message: '服务器错误 ' + response.statusText,
            type: 'error',
            duration: 5000,
            showClose: true
          })
          break
        case 504: //=>超时
          ElMessage({
            message: '网关超时 ' + response.statusText,
            type: 'error',
            duration: 5000,
            showClose: true
          })
          break
        default:
          //=>以上都不是
          ElMessage({
            message: '服务器错误 ' + response.statusText,
            type: 'error',
            duration: 5000,
            showClose: true
          })
          break
      }
      return Promise.reject(error)
    }
  )
  axios.isInterceptorAdded = true
}
export async function unauthorized() {
  if (!isShow) {
    return
  }
  isShow = false
  try {
    await ElMessageBox.alert('登录信息过期，请重新登录', '温馨提示', {
      confirmButtonText: '知道了'
    })
  } finally {
    isShow = true
    router.push('/login')
  }
}

export const service = axios

export const post = (url, data, config) => {
  return axios.post(url, data, config)
}

export const get = (url, params, config) => {
  return axios.get(url, { params, ...config })
}

export const _delete = (url, params, config) => {
  return axios.delete(url, { params, ...config })
}

export const postForm = (url, data, config) => {
  return axios.postForm(url, data, config)
}
